﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using HalconDotNet;
using MachineVision.Core.Extensions;
using MachineVision.Core.TemplateMatch.Shared;
using Prism.Mvvm;
using static MaterialDesignThemes.Wpf.Theme.ToolBar;

namespace MachineVision.Core.CircleMeasure
{
    public class CircleMeasureService : BindableBase
    {
        public CircleMeasureService()
        {
            RunParameter = new CircleRunParameter();
            Info = new MethodInfo()
            {
                Name = "find_circle",
                Description = "Add a circle or a circular arc to a metrology model",
                Parameters = new List<MethodParameter>()
                {
                    new MethodParameter()
                    {
                        Name = "Row",
                        Description =
                            "Row coordinate (or Y) of the center of the circle or circular arc."
                    },
                    new MethodParameter()
                    {
                        Name = "Column",
                        Description =
                            "Column (or X) coordinate of the center of the circle or circular arc."
                    },
                    new MethodParameter()
                    {
                        Name = "Radius",
                        Description = "Radius of the circle or circular arc."
                    },
                    new MethodParameter()
                    {
                        Name = "MeasureLength1",
                        Description =
                            "Half length of the measure regions perpendicular to the boundary."
                    },
                    new MethodParameter()
                    {
                        Name = "MeasureLength2",
                        Description =
                            "Half length of the measure regions tangential to the boundary."
                    },
                    new MethodParameter()
                    {
                        Name = "MeasureSigma",
                        Description = "Sigma of the Gaussian function for the smoothing."
                    },
                    new MethodParameter()
                    {
                        Name = "MeasureThreshold",
                        Description = "Minimum edge amplitude."
                    },
                    new MethodParameter()
                    {
                        Name = "GenParamName",
                        Description = "Names of the generic parameters.Default: []"
                    },
                    new MethodParameter()
                    {
                        Name = "GenParamValue",
                        Description = "Values of the generic parameters."
                    },
                    new MethodParameter()
                    {
                        Name = "Index",
                        Description = "Index of the created metrology object."
                    },
                },
                Preducessors = new List<string>()
                {
                    "align_metrology_model",
                    "apply_metrology_model"
                }
            };

            MatchResult = new CircleMeasureMatchResult();
        }

        HTuple hv_Parameter = new HTuple();
        HObject ho_Contour1;

        public void Run(HObject image)
        {
            CircleMeasureMatchResult matchResult = new CircleMeasureMatchResult();

            var act = () =>
            {
                HTuple hv_MetrologyHandle = new HTuple();
                HTuple hv_Index = new HTuple(),
                    hv_Row1 = new HTuple();
                HTuple hv_Column1 = new HTuple();
                HObject ho_GrayImage,
                    ho_Contours;
                HOperatorSet.GenEmptyObj(out ho_GrayImage);
                HOperatorSet.GenEmptyObj(out ho_Contours);
                HOperatorSet.GenEmptyObj(out ho_Contour1);
                //创建几何测量模型的数据结构
                hv_MetrologyHandle?.Dispose();
                HOperatorSet.CreateMetrologyModel(out hv_MetrologyHandle);
                //将圆添加到几何测量模型中
                //row column radius 中点坐标和半径
                //20,5,1,30  卡尺尺寸 边缘系数 边缘阈值
                hv_Index?.Dispose();
                HOperatorSet.AddMetrologyObjectCircleMeasure(
                    hv_MetrologyHandle,
                    RunParameter.Row,
                    RunParameter.Column,
                    RunParameter.Radius,
                    RunParameter.MeasureLength1,
                    RunParameter.MeasureLength2,
                    RunParameter.MeasureSigma,
                    RunParameter.MeasureThreshold,
                    new HTuple(),
                    new HTuple(),
                    out hv_Index
                );

                ho_GrayImage?.Dispose();
                HOperatorSet.Rgb1ToGray(image, out ho_GrayImage);
                //显示几何测量模型的轮廓。
                ho_Contours?.Dispose();

                ho_Contours = null;

                hv_Row1?.Dispose();
                hv_Column1?.Dispose();
                HOperatorSet.GetMetrologyObjectMeasures(
                    out ho_Contours,
                    hv_MetrologyHandle,
                    "all",
                    "all",
                    out hv_Row1,
                    out hv_Column1
                );

                //测量并拟合网络节点的所有计量对象的几何形状。
                HOperatorSet.ApplyMetrologyModel(ho_GrayImage, hv_MetrologyHandle);
                //获取计量模型的测量结果。
                hv_Parameter?.Dispose();
                HOperatorSet.GetMetrologyObjectResult(
                    hv_MetrologyHandle,
                    0,
                    "all",
                    "result_type",
                    "all_param",
                    out hv_Parameter
                );
                if (hv_Parameter.Length <= 0)
                    throw new Exception("未匹配到结果");
                //查询计量对象的结果轮廓。
                ho_Contour1?.Dispose();
                ho_Contour1 = null;
                HOperatorSet.GetMetrologyObjectResultContour(
                    out ho_Contour1,
                    hv_MetrologyHandle,
                    0,
                    "all",
                    1.5
                );
                if (HWindow != null)
                {
                    HOperatorSet.SetColor(HWindow, "green");
                    HOperatorSet.DispObj(ho_Contour1, HWindow);
                    HOperatorSet.SetColor(HWindow, "red");
                    HOperatorSet.DispObj(ho_Contours, HWindow);
                    HOperatorSet.SetColor(HWindow, "green");
                    HOperatorSet.DispCross(
                        HWindow,
                        hv_Parameter.DArr[0],
                        hv_Parameter.DArr[1],
                        20,
                        0
                    );
                    HOperatorSet.SetColor(HWindow, "green");
                    HWindow.SetString(
                        $"{hv_Parameter.DArr[0].RetainLen(3)} : {hv_Parameter.DArr[1].RetainLen(3)} : {hv_Parameter.DArr[2].RetainLen(3)} ",
                        "image",
                        hv_Parameter.DArr[0].RetainLen(3) + 5,
                        hv_Parameter.DArr[1].RetainLen(3) + 5,
                        "black",
                        "true"
                    );
                }
            };
            var timespan = act.SetTimer();
            matchResult.IsSuccess = true;
            matchResult.Contour = ho_Contour1;
            matchResult.Row = hv_Parameter.DArr[0];
            matchResult.Column = hv_Parameter.DArr[1];
            matchResult.Radius = hv_Parameter.DArr[2];
            matchResult.Message =
                $"{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}：识别耗时：{timespan}ms,识别结果：{hv_Parameter.ToString()}}}";
            MatchResult = matchResult;
        }

        #region props
        private CircleMeasureMatchResult matchresult;

        public CircleMeasureMatchResult MatchResult
        {
            get { return matchresult; }
            set
            {
                matchresult = value;
                RaisePropertyChanged();
            }
        }

        private CircleRunParameter runParameter;

        public CircleRunParameter RunParameter
        {
            get { return runParameter; }
            set { runParameter = value; }
        }

        /// <summary>
        /// 算子描述信息
        /// </summary>
        public MethodInfo Info { get; set; }

        /// <summary>
        /// 窗口
        /// </summary>
        public HWindow HWindow { get; set; }

        #endregion


        private ROIParameter roi;

        public ROIParameter ROI
        {
            get { return roi; }
            set { roi = value; }
        }
    }
}
